#pragma once
#include "Window.h"
namespace NBE
{
	class NBE_API GLWindow: public RendererWindow
	{
	public:
		GLWindow(HINSTANCE h, RenderInfo* ri)
			:RendererWindow(h),m_renderInfo(ri)
		{
			registerClass(h);
			//change size of window to get correct pixel-level size of the window.
			RECT _windowRect = { 0, 0, ri->width, ri->height };
			AdjustWindowRectEx(&_windowRect,WS_OVERLAPPEDWINDOW,NULL,CW_USEDEFAULT);

			m_hwnd = CreateWindowEx(WS_EX_CONTROLPARENT,ri->className, ri->title, WS_OVERLAPPEDWINDOW,
				CW_USEDEFAULT, 0, (_windowRect.right - _windowRect.left),
				(_windowRect.bottom - _windowRect.top), NULL, NULL, h, NULL);


			ShowWindow(m_hwnd, SW_SHOWNORMAL);
			UpdateWindow(m_hwnd);



			if (!m_hwnd)
			{
				throw NBEException(CreateWindowError);
			}

			//TODO: fix it, dont save the pointer
			::SetWindowLongPtrW(m_hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));

		}
		~GLWindow()
		{
			delete m_renderInfo;
		}
	private:
		static LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
		{
			//static func
			PAINTSTRUCT ps;
			HDC hdc;

			GLWindow* win = reinterpret_cast<GLWindow*>(::GetWindowLongPtrW(hWnd, GWLP_USERDATA));
			if(win!=NULL)
			{
				win->procMsg(hWnd,message,wParam,lParam);// custom msg processing
			}


			switch (message)
			{
			case WM_COMMAND:
				break;
			case WM_PAINT:
				hdc = BeginPaint(hWnd, &ps);
				EndPaint(hWnd, &ps);
				break;
			case WM_DESTROY:
				PostQuitMessage(0);
				break;
			default:
				return DefWindowProc(hWnd, message, wParam, lParam);
			}
			return 0;
		}
		ATOM registerClass(HINSTANCE hInstance)
		{
			WNDCLASSEX wcex;

			wcex.cbSize = sizeof(WNDCLASSEX);

			wcex.style			= CS_HREDRAW | CS_VREDRAW;
			wcex.lpfnWndProc	= WndProc;
			wcex.cbClsExtra		= 0;
			wcex.cbWndExtra		= 0;
			wcex.hInstance		= hInstance;
			wcex.hIcon			= LoadIcon(hInstance, IDI_APPLICATION);
			wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
			wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
			wcex.lpszMenuName	= nullptr;//MAKEINTRESOURCE(IDC_THREADING);
			wcex.lpszClassName	= m_renderInfo->className;
			wcex.hIconSm		= nullptr;

			return RegisterClassEx(&wcex);
		}
		void procMsg(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
		{
			std::for_each(std::begin(*m_inputVec),std::end(*m_inputVec),[&](Input* input){
			input->processMessages(hWnd,message,wParam,lParam);
			});
		}

	private:
		RenderInfo* m_renderInfo;
	};
}